<template>
    <el-upload list-type="picture-card" :auto-upload="false" :on-change="onChange" :on-remove="onRemove"
        :multiple="props.multiple" :limit="props.limit" :accept="accept" ref="elUploadElement" :file-list="fileList"
        :id="fileUploadId" :disabled="disabled">
        <el-icon>
            <Plus />
        </el-icon>

        <template #file="{ file }">
            <div>
                <img class="el-upload-list__item-thumbnail" :src="file.viewUrl" alt="" v-if="isShow" />
                <span class="el-upload-list__item-actions">
                    <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                        <el-icon><zoom-in /></el-icon>
                    </span>
                    <span class="el-upload-list__item-delete" @click="handleRemove(file)" v-if="!disabled">
                        <el-icon>
                            <Delete />
                        </el-icon>
                    </span>
                </span>
            </div>
        </template>
        <template #tip>
            <div class="el-upload__tip">
                {{ tip }}
            </div>
        </template>
    </el-upload>
    <!-- 图片预览弹窗 -->
    <el-dialog v-model="dialogVisible" style="width: 800px">
        <el-image v-if="previewFile.type === 'image'" style="width: 100%; height: 400px" :src="previewFile.url"
            fit="contain" alt="Preview Image" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2"
            :preview-src-list="[previewFile.url]" :initial-index="0" />
    </el-dialog>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { Delete, Plus, ZoomIn } from "@element-plus/icons-vue";
import type { UploadFile } from "element-plus";
import { buildUUID } from "@pureadmin/utils";
const fileUploadId = ref("ID" + buildUUID().slice(0, 12));
type UploadFileNew = {
    [Property in keyof UploadFile]: UploadFile[Property];
} & {
    type: string;
    viewUrl: string | undefined;
    needUpload: boolean;
    duration: number;
    width: number;
    height: number;
    process: boolean;
};

const props = defineProps({
    // 数量限制
    limit: {
        type: Number,
        default: 1
    },
    minLimit: {
        type: Number,
        default: -1
    },
    //是否支持多选文件
    multiple: {
        type: Boolean,
        default: false
    },
    // 限制文件类型
    fileType: {
        type: String,
        required: true,
        validator(value: string) {
            return ["image"].includes(value);
        }
    },
    appendTip: {
        type: String,
        default: ""
    },
    widthLimit: {
        type: Number,
        default: 0
    },
    heightLimit: {
        type: Number,
        default: 0
    },
    maxSize: {
        type: Number,
        default: 0
    },
    accept: {
        type: String,
        default: ""
    },
    disabled: {
        type: Boolean,
        default: false
    },
    required: {
        type: Boolean,
        default: true
    },
});
const emits = defineEmits(["changeFileList"]);
// 可上传文件类型
const accept = ref(props.accept);
// 最大上传文件大小
const maxSize = ref(props.maxSize);
const tip = ref("");
// 根据类型设置默认值
if (props.fileType) {
    switch (props.fileType) {
        case "image":
            accept.value = accept.value || ".png, .jpg, .jpeg, .webp";
            maxSize.value = maxSize.value || 20;
            // tip.value = `请上传${accept.value}格式的文件，图片大小不能超过${maxSize.value}MB。${props.appendTip}`;
            tip.value = `请上传${accept.value}格式的文件${props.appendTip}`;
            break;
        default:
            throw new Error("类型错误");
    }
}
const isShow = ref(true);
const elUploadElement = ref();
// 控制图片预览的路径
const previewFile = ref();
// 控制是否显示图片预览的弹窗
const dialogVisible = ref(false);
// 双向绑定的文件列表
const fileList = ref<UploadFileNew[]>([]);
//删除文件
function onRemove(uploadFile: UploadFileNew, uploadFiles: UploadFileNew[]) {
    verifyLength();
    fileList.value = uploadFiles;
    emits("changeFileList", uploadFile, "remove");
}
async function onChange(
    uploadFileC: UploadFileNew,
    uploadFiles: UploadFileNew[]
) {
    // console.log("onChange", uploadFileC, uploadFiles);
    const uploadFile = uploadFileC;
    try {
        // 如果是远程原件不需要任何处理
        if (!uploadFile.name) return;
        // 如果被处理过则不再处理
        if (uploadFile.process) return;
        isShow.value = false;
        const suffix = uploadFile.name.split(".").at(-1);
        uploadFile.type = "image";
        uploadFile.viewUrl = uploadFile.url;

        uploadFile.needUpload = true;
        uploadFile.process = true;
    } catch (e) {
        console.error(e);
    }
    fileList.value.push(uploadFile);
    isShow.value = true;
    verifyLength();
    emits("changeFileList", uploadFileC, uploadFiles);
}

// 删除文件
function handleRemove(uploadFile: UploadFile) {
    elUploadElement.value.handleRemove(uploadFile);
    verifyLength();
}

// 检验已选择的文件数量是否超过阈值，并做显示/隐藏处理
function verifyLength() {
    const element = document.querySelector(
        `#${fileUploadId.value} .el-upload--picture-card`
    ) as HTMLDivElement;
    if (fileList.value.length === props.limit) {
        element.style.visibility = "hidden";
    } else {
        element.style.visibility = "visible";
    }
}

// 预览文件
const handlePictureCardPreview = (file: UploadFile) => {
    previewFile.value = file;
    dialogVisible.value = true;
};

type validateReturnValue = {
    code: number;
    success: boolean;
    msg: string;
};
// 验证文件格式
function verification(): validateReturnValue {
    if (props.required && fileList.value.length <= 0) {
        return {
            code: 0,
            success: false,
            msg: "请选择上传文件"
        };
    }
    if (fileList.value.length > props.limit) {
        return {
            code: 0,
            success: false,
            msg: `文件数量超出限制，请上传${props.limit}个及以内的文件`
        };
    }
    if (props.minLimit > 0 && fileList.value.length < props.minLimit) {
        return {
            code: 0,
            success: false,
            msg: `文件数量低于最少限制，请上传${props.minLimit}个及以上的文件`
        };
    }

    for (let i = 0; i < fileList.value.length; i++) {
        const element = fileList.value[i];
        if (!element.needUpload) break;
        if (element.size / 1024 / 1024 > maxSize.value) {
            return {
                code: 0,
                success: false,
                msg: "文件大小超出限制"
            };
        }
        if (element.type === "image") {
            if (props.widthLimit && element.width != props.widthLimit) {
                return {
                    code: 0,
                    success: false,
                    msg: `图片宽度不等于${props.widthLimit}像素`
                };
            }
            if (props.heightLimit && element.height != props.heightLimit) {
                return {
                    code: 0,
                    success: false,
                    msg: `图片高度不等于${props.heightLimit}像素`
                };
            }
        }
        if (!accept.value.includes(element.name.split(".").at(-1).toLowerCase())) {
            return {
                code: 0,
                success: false,
                msg: `文件类型不正确，请上传${accept.value}类型的文件`
            };
        }
    }
    return {
        code: 200,
        success: true,
        msg: "格式正确"
    };
}

// 添加远程图片
async function addFileList(url: string, name?: string) {
    const uploadFile: any = {
        url,
        name
    };
    const suffix = url.split(".").at(-1);
    uploadFile.type = "image";
    uploadFile.viewUrl = uploadFile.url;
    uploadFile.needUpload = false;
    fileList.value.push(uploadFile);
    verifyLength();
}


// 获取文件对象
function getFiles(): UploadFileNew[] {
    return fileList.value;
}
// 清理文件
function clearFileList() {
    fileList.value = [];
    verifyLength();
}

defineExpose({
    getFiles,
    verification,
    addFileList,
    clearFileList,
    handlePictureCardPreview,
    handleRemove
});
</script>